<template>
  <el-container>
    <el-header class="mt-2.5">
      <el-row>
        <el-col :span="16">
          <div class="flex h-10 items-center justify-around">
            <div>督学室名称: {{ roomInfo.name }}</div>
            <div>学员数: {{ count }}</div>
            <div>创建时间: {{ roomInfo.create_time | newDate }}</div>
          </div>
        </el-col>
        <el-col :span="7">
          <div class="float-right">
            <el-button type="primary" @click="exitTeaching()">退出督学</el-button>
            <el-button icon="el-icon-refresh-right" type="primary">刷新</el-button>
          </div>
        </el-col>
      </el-row>
    </el-header>
    <el-container>
      <el-main class="flex flex-col items-center">
        <div class="flex">
          <div class="w-[640px] m-2.5">
            <div class="flex justify-around items-center text-sm">
              <div>账号:{{ tempStudent.account }}</div>
              <div>姓名:{{ tempStudent.username }}</div>
              <div>年级:{{ tempStudent.gradeName }}</div>
            </div>
            <div id="remote-video" class="bg-black h-[400px]"></div>
            <div class="flex justify-around items-center mt-2.5">
              <el-switch v-model="teach" active-text="远程督学" @change="setTeachingStatus"></el-switch>
              <el-button size="mini" @click="toControlScreen" type="primary">远程控屏</el-button>
              <el-switch :disabled="!teach" v-model="mike" active-text="麦克风" @change="changeMike"></el-switch>
              <el-switch :disabled="!teach" v-model="camera" active-value="1" inactive-value="0" active-text="摄像头" inactive-text="屏幕" @change="changeCamera"></el-switch>
            </div>
          </div>
          <div style="display: flex; flex-direction: column; justify-content: space-around; align-items: flex-end">
            <el-button size="mini" @click="tipsVisible=true">发送提醒</el-button>
            <el-button size="mini" @click="lockVisible=true">远程锁屏</el-button>
            <el-button size="mini" @click="screeShotVisible=true">远程截屏</el-button>
          </div>
        </div>
        <div style="width: 100%">
          <span class="text-slate-400 leading-6">任务完成情况:</span>
          <el-tabs v-model="taskType" type="card" @tab-click="handleTaskClick">
            <el-tab-pane label="当前任务" name="current"></el-tab-pane>
            <el-tab-pane label="日任务" name="day"></el-tab-pane>
            <el-tab-pane label="周任务" name="week"></el-tab-pane>
            <el-tab-pane label="月任务" name="month"></el-tab-pane>
            <el-tab-pane label="所有任务" name="all"></el-tab-pane>
          </el-tabs>
          <el-table stripe style="width: 100%" border fit highlight-current-row :data="taskTableData">
            <el-table-column min-width="50" align="center" prop="id" label="ID"></el-table-column>
            <el-table-column min-width="50" align="center" prop="username" label="姓名"></el-table-column>
            <el-table-column min-width="50" align="center" prop="gradeName" label="年级"></el-table-column>
            <el-table-column min-width="50" align="center" prop="subjectName" label="学科"></el-table-column>
            <el-table-column min-width="100" align="center" prop="date_type" label="任务类别">
              <template slot-scope="scope">
                <span v-if="scope.row.date_type===1">日任务</span>
                <span v-else-if="scope.row.date_type===2">周任务</span>
                <span v-else>月任务</span>
              </template>
            </el-table-column>
            <el-table-column min-width="100" align="center" prop="name" label="任务名称"></el-table-column>
            <el-table-column v-if="taskType==='current'" min-width="80" align="center" prop="username" label="当前情况">
              <template slot-scope="scope">
                <span v-if="scope.row.is_done===1" style="color: #67C23A">已完成</span>
                <span v-else style="color: #F56C6C">未完成</span>
              </template>
            </el-table-column>
            <el-table-column min-width="80" align="center"  label="整体情况">
              <template slot-scope="scope">
                <span>{{scope.row.done_num}}/{{scope.row.task_num}}</span>
              </template>
            </el-table-column>
            <el-table-column min-width="100" align="center"  label="任务有效期">
              <template slot-scope="scope">
                <div v-if="scope.row.date_type === 1 || scope.row.date_type === 2">
                  <span>{{scope.row.expire_start_day}}</span>
                  <span>{{scope.row.expire_end_day}}</span>
                </div>
                <div v-else>
                  <span>{{scope.row.date_select}}</span>
                </div>
              </template>
            </el-table-column>
            <el-table-column min-width="100" align="center" prop="create_time" label="创建日期">
              <template slot-scope="scope">
                <span>{{scope.row.create_time | newDate}}</span>
              </template>
            </el-table-column>
            <el-table-column min-width="80" align="center" prop="admin_name" label="创建人"></el-table-column>
            <el-table-column label="操作" align="center">
              <template slot-scope="scope">
                <el-row>
                  <el-button  size="mini" type="primary" @click="openDetailTask(scope.row.id)">查看详情</el-button>
                </el-row>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </el-main>
      <el-aside style="width: 400px; margin-right: 20px; height: 700px;overflow: auto">
        <el-scrollbar>
          <div class="top_box" v-for="student in studentArr" :key="student.id" :id="'studentScreen'+ student.id" @dblclick="setTempStudent(student)">
            <div class="flex flex-col flex-wrap content-end h-24 justify-around">
              <el-image v-show="student.noPeople" style="width: 20px; height: 20px" src="https://jiaoguanyi008.oss-cn-shenzhen.aliyuncs.com/img/noPeople.png" @click="openFeedback('noPeople', student)"></el-image>
              <el-image v-show="student.noClick" style="width: 20px; height: 20px" src="https://jiaoguanyi008.oss-cn-shenzhen.aliyuncs.com/img/noClick.png" @click="openFeedback('noClick', student)"></el-image>
              <el-image v-show="student.handsup" style="width: 20px; height: 20px" src="https://jiaoguanyi008.oss-cn-shenzhen.aliyuncs.com/img/greenHand.png" @click="openFeedback('handsUp', student)"></el-image>
              <div v-show="student.status==3" class="text-xs text-amber-600">请假中</div>
            </div>
            <div class="flex justify-between items-center pt-10  ml-1 mr-1">
              <div class="text-sm text-amber-600">
                <div>账号:{{ student.account }}</div>
                <div>姓名:{{ student.username }}</div>
                <div>年级:{{ student.gradeName }}</div>
              </div>
              <div class="text-sm text-amber-600" @click="openAddMoney(student)">奖励币</div>
            </div>
          </div>
        </el-scrollbar>
      </el-aside>
      <el-dialog title="发送提醒" :visible.sync="tipsVisible" width="35%">
        <el-input v-model="tips" placeholder="请输入提醒文字"></el-input>
        <span slot="footer" class="dialog-footer">
          <el-button @click="tipsVisible = false">取 消</el-button>
          <el-button type="primary" @click="sendTips">发送</el-button>
        </span>
      </el-dialog>
      <el-dialog :title="tempStudent.isLock===0 ? '远程锁屏': '远程解锁'" :visible.sync="lockVisible" width="30%">
        <div v-if="tempStudent.isLock===0">
          <el-input v-model="lockText" placeholder="请输入锁屏界面提醒文字"></el-input>
          <span slot="footer" class="dialog-footer">
          <el-button @click="lockVisible = false">取 消</el-button>
          <el-button type="primary" @click="sendLock">发送</el-button>
          </span>
        </div>
        <div v-else>
          <el-button type="primary" @click="sendCancelLock">确定</el-button>
          <el-button @click="lockVisible = false">取 消</el-button>
        </div>
      </el-dialog>

      <el-dialog title="奖励彩虹币" :visible.sync="moneyVisible" width="25%">
        <el-select v-model="moneyForm.money" placeholder="请选择">
          <el-option :value="3" label="3彩虹币"></el-option>
          <el-option :value="5" label="5彩虹币"></el-option>
          <el-option :value="10" label="10彩虹币"></el-option>
        </el-select>
        <span slot="footer" class="dialog-footer">
          <el-button @click="moneyVisible = false">取 消</el-button>
          <el-button type="primary" @click="addStudentMoney">发送</el-button>
        </span>
      </el-dialog>

      <el-dialog title="远程截屏" :visible.sync="screeShotVisible" width="35%" @opened="openScreenShot">
        <div class="flex justify-center w-full">
          <el-button type="primary" size="mini" @click="remoteScreenshot">远程截屏</el-button>
        </div>
        <div class="pt-3 flex justify-center w-full">
          <img id="screenImg" style="display: none"/>
        </div>
      </el-dialog>
      <el-dialog title="反馈信息" :visible.sync="feedbackVisible" width="30%">
        <span>{{ feedbackForm.feedbackText }}</span>
        <div slot="footer" class="dialog-footer">
          <el-button @click="closeFeedback">误报</el-button>
          <el-button type="primary" @click="reduceStudentMoney">确认</el-button>
        </div>
      </el-dialog>

      <el-dialog title="远程控屏"  top="0" :visible.sync="remoteVisible" fullscreen :before-close="closeRemoteControl" :close-on-click-modal="false" custom-class="custom-dialog">
        <div ref="wrapper" class="wrapper" v-show="!showLoading"></div>
        <div v-show="showLoading" class="msg-placeholder" id="msg">
          <div class="loading" id="loading-animate">
            <span></span><span></span><span></span><span></span><span></span>
          </div>
          <span id="msg-text" class="msg-text">{{ msgText }}</span>
        </div>
      </el-dialog>
      <el-dialog title="任务详情" :visible.sync="taskDetailVisible" :close-on-click-modal="false" :close-on-press-escape="false" width="40%">
        <el-descriptions :column="2" border>
          <el-descriptions-item label="任务类别" :contentStyle="{'text-align': 'left'}">{{taskInfo.dateExplain}}</el-descriptions-item>
          <el-descriptions-item label="有效期">{{taskInfo.expireExplain}}</el-descriptions-item>
          <el-descriptions-item label="跳转方式">{{taskInfo.jumpExplain}}</el-descriptions-item>
          <el-descriptions-item label="提醒时间">{{taskInfo.remindExplain}}</el-descriptions-item>
          <el-descriptions-item label="责任老师">{{taskInfo.teacherName}}</el-descriptions-item>
          <el-descriptions-item label="任务名称">{{taskInfo.name}}</el-descriptions-item>
          <el-descriptions-item label="任务内容">{{taskInfo.remark}}</el-descriptions-item>
        </el-descriptions>
        <el-table stripe style="width: 100%" border fit highlight-current-row :data="taskDetailData" :key="1">
          <el-table-column min-width="50" align="center" prop="id" label="ID"></el-table-column>
          <el-table-column min-width="50" align="center" prop="username" label="姓名"></el-table-column>
          <el-table-column min-width="50" align="center" prop="gradeName" label="年级"></el-table-column>
          <el-table-column min-width="50" align="center" prop="subjectName" label="学科"></el-table-column>
          <el-table-column min-width="110" align="center" prop="lll" label="任务日期"></el-table-column>
          <el-table-column min-width="80" align="center" label="完成情况">
            <template slot-scope="scope">
              <span v-if="scope.row.is_done===1" style="color: #67C23A">已完成</span>
              <span v-else style="color: #F56C6C">未完成</span>
            </template>
          </el-table-column>
          <el-table-column min-width="80" align="center" prop="done_time" label="完成时间"></el-table-column>
        </el-table>
      </el-dialog>
    </el-container>
  </el-container>
</template>

<script>
import {ZegoExpressEngine} from "zego-express-engine-webrtc";
import {
  checkAvRemainTime,
  closeRemoteVoiceVideo,
  endTeaching,
  getStudentByCourseId, getTaskDetail,
  openRemoteControl, openRemoteVoiceVideo, queryStudentTaskById, setStudentMoney,
} from "@/api/teacher";
import mqttHandle from "@/utils/mqttHandler";
import {generateToken04} from "@/server/zegoServerAssistant";
import pako from "pako"
import {debounce} from 'lodash'

var zg = null
var client = null  //mqtt的实例
var localStream = null
var sunClient = null  //向日葵实例
var keyboardHandler = null; // 接收键盘事件的句柄
var mouseHandler = null; // 接收鼠标事件的句柄

export default {
  name: "index",
  data() {
    return {
      courseId: this.$route.query.courseId,
      teacherId: this.$route.query.teacherId,
      count: 0,
      dialogVisible: false,
      teach: false,  //远程督学开关
      screen: false, //远程控屏开关
      mike: false, //麦克风开光
      camera: "0", //摄像头开关
      tipsVisible: false,
      tips: '',
      lockVisible: false,
      lockText: '',
      isLock: false, //是否在锁屏状态
      moneyVisible: false,
      screeShotVisible: false, //远程截屏
      moneyForm: {studentId: 0, money: ''},
      studentArr: [],
      topicSends: [], //订阅的topic 例如：["Time1", "EngineMain1", "Console1", "Location1"]
      tempStudent: [],
      studentTaskData: [],
      roomInfo: {},
      feedbackVisible: false,
      feedbackForm: {studentId: 0, feedbackText: '', type: ''},
      remoteVisible: false,
      showLoading: true,
      totalBytes: 0,
      view: null,
      framesCount: 0,
      msgText: '正在加载程序...',
      intervalId: 0,
      taskType: 'current',
      taskTableData: [],
      taskDetailVisible: false,
      taskDetailData: [],
      taskInfo: [],
    }
  },
  created() {
    this.$nextTick(() => {
      this.createZegoExpressEngine()
      this.getStudents()
    })
  },
  beforeDestroy() {
    clearInterval(this.intervalId)
    if (localStream) {
      zg.destroyStream(localStream)
    }
    this.logoutRoom()
    this.disConnect()
  },
  beforeRouteLeave(to, from, next) {
    setTimeout(() => {
      this.$confirm('您正在督学中,若离开当前页面将退出督学', '离开页面', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.endTeachingControl()
        if (this.teach) {
          closeRemoteVoiceVideo({
            teacherId: this.teacherId,
            studentId: this.tempStudent.id,
            type: 1
          }).then(res => {
          })
        }
        next()
      }).catch(() => {
        next(false)
      })
    }, 200)
  },
  methods: {
    createZegoExpressEngine() {
      zg = new ZegoExpressEngine(1160897212, "wss://webliveroom1160897212-api.imzego.com/ws");
      zg.setLogConfig({logLevel: "warn"})
      // zg.setDebugVerbose({enabled: true})
      // 房间状态更新回调
      zg.on('roomStateChanged', (roomID, reason, errorCode, extendData) => {
        if (reason == 'LOGINING') {
          // 登录中
        } else if (reason == 'LOGINED') {
          // 登录成功
          //只有当房间状态是登录成功或重连成功时，推流（startPublishingStream）、拉流（startPlayingStream）才能正常收发音视频
          //将自己的音视频流推送到 ZEGO 音视频云
        } else if (reason == 'LOGIN_FAILED') {
          // 登录失败
        } else if (reason == 'RECONNECTING') {
          // 重连中
        } else if (reason == 'RECONNECTED') {
          // 重连成功
        } else if (reason == 'RECONNECT_FAILED') {
          // 重连失败
        } else if (reason == 'KICKOUT') {
          // 被踢出房间
        } else if (reason == 'LOGOUT') {
          // 登出成功
        } else if (reason == 'LOGOUT_FAILED') {
          // 登出失败
        }
      });
      //房间内其他用户进出房间的通知
      //只有调用 loginRoom 登录房间时传入 ZegoRoomConfig，且 ZegoRoomConfig 的 userUpdate 参数为 “true” 时，用户才能收到 roomUserUpdate回调。
      zg.on('roomUserUpdate', (roomID, updateType, userList) => {
        if (updateType == 'ADD') {
          for (var i = 0; i < userList.length; i++) {
            console.log(userList[i]['userID'], '加入了房间：', roomID)
          }
        } else if (updateType == 'DELETE') {
          for (var i = 0; i < userList.length; i++) {
            console.log(userList[i]['userID'], '退出了房间：', roomID)
          }
        }
      });
      zg.on('roomStreamUpdate', async (roomID, updateType, streamList, extendedData) => {
        // 房间内其他用户音视频流变化的通知
        if (updateType === 'ADD') {
          //流新增,开始拉流
          for (var i = 0; i < streamList.length; i++) {
            // console.log("这是增加的流", streamList)
            if (streamList[i]['streamID'] == this.tempStudent.id) {
              await this.pullStream(streamList[i]['streamID'])
            }
          }
        } else if (updateType === 'DELETE') {
          // console.log("这是删除的流", roomID, updateType, streamList)
          for (var i = 0; i < streamList.length; i++) {
            zg.stopPlayingStream(streamList[i]['streamID'])
          }
        }
      });
    },
    // Step3 Login room
    async loginRoom(userID, username) {
      let token = generateToken04(1160897212, userID, '946fc28a69cf45af5bccce6caa331340', 86400, '')
      const result = await zg.loginRoom(this.courseId.toString(), token, {
        userID: userID,
        userName: username
      }, {userUpdate: true})
      return result
    },
    async pullStream(streamID) {
      const remoteStream = await zg.startPlayingStream(streamID);
      // 创建媒体流播放组件
      const remoteView = zg.createRemoteStreamView(remoteStream);
      remoteView.play("remote-video", {enableAutoplayDialog: true});
      // 注册 playerStateUpdate 拉流状态更新事件回调。
      zg.on('playerStateUpdate', ({streamID, state}) => {
        // streamID 为拉流的流 ID，state 为拉流状态。 可以根据这些状态做一些逻辑处理。
      })
      // 注册 playQualityUpdate 拉流质量更新事件回调。
      zg.on('playQualityUpdate', (streamID, stats) => {
        // stats 对象中可以拿到分辨率、帧率、码率等流质量相关信息做数据展示。
      })
    },
    //streamID 推送流ID type 1:音频通话 2:屏幕共享 3: 视频通话
    async pushStream(streamID, type) {
      let options = {camera: {video: false, audio: true}}  //音频通话
      if (type === 2) {
        options = {screen: {video: true, audio: true}}
      } else if (type === 3) {
        options = {camera: {video: true, audio: true}}
      }
      localStream = await zg.createZegoStream(options);
      zg.startPublishingStream(streamID, localStream)
    },
    async logoutRoom() {
      zg.logoutRoom(this.courseId.toString())
    },

    getStudents() {
      getStudentByCourseId({
        courseId: this.courseId,
      }).then(res => {
        this.studentArr = res.data
        this.roomInfo = res.otherData
        if (this.studentArr.length > 0) {
          this.tempStudent = this.studentArr[0]
          this.count = this.studentArr.length
          this.queryStudentTask(this.taskType)
        }
        this.setTopic(res.data)
        this.createMqtt()
      }).catch(err => {
        this.studentArr = []
      })
    },
    setTopic(data) {
      let that = this
      data.forEach(function (element) {
        let topic = '/control/is_online/' + element.account
        if (!that.topicSends.includes(topic)) {
          that.topicSends.push(topic)
        }
      })
    },
    setTempStudent(student) {
      let docId = "studentScreen" + student.id
      const element = document.getElementById(docId)
      if (element) {
        element.style.border = "6px solid green"
      }
      if (this.tempStudent.id !== student.id) {
        this.doPublish("command", 1, "", false)  //上对一个学生发送停止推流
        this.doPublish("command", 5, "", false)
        //上一个学生取消选中特效
        let prevId = "studentScreen" + this.tempStudent.id
        const element = document.getElementById(prevId)
        if (element) {
          element.style.border = ""
        }
        this.tempStudent = student
        if (this.teach) { //开启远程督学时
          let streamId = "teacher" + this.teacherId;
          this.doPublish("command", 0, streamId, false) //对现在的这个学生发送开始推流
          setTimeout(() => {
            if (this.mike) {
              this.doPublish("command", 4, "这是延迟", false)
            }
          }, 500)
        }
        this.queryStudentTask(this.taskType)

      }
    },
    decompressToImgUrl(base64Data) {
      // 将 Base64 编码的字符串解码为二进制字符串
      const binaryString = atob(base64Data);
      const byteArray = new Uint8Array(binaryString.length);
      for (let i = 0; i < binaryString.length; i++) {
        byteArray[i] = binaryString.charCodeAt(i);
      }
      // 使用pako.inflate解压缩数据
      const decompressedData = pako.inflate(byteArray, {to: 'uint8array'});
      // 创建 Blob 对象并生成 URL，以便可以在 Image 对象中使用
      const blob = new Blob([decompressedData], {type: 'image/webp'});
      return URL.createObjectURL(blob);
    },
    /**创建mqtt**/
    createMqtt() {
      var mqtt; //mqtt 处理对象（全局变量）
      //创建链接，接收数据
      if (!client) {
        mqtt = new mqttHandle(['/control/#']);
        client = mqtt.createConnect();
      }
      client.on("message", (topic, message) => {
        //数据分类
        try {
          let messageData = JSON.parse(message)
          let arr = topic.split('/')
          let studentId = arr[2]
          let type = arr[3]
          if (type === 'report') {
            switch (messageData.messageType) {
              case 200: //无人监测上报消息
                this.studentArr.forEach((item, index, arr) => {
                  if (item.id == studentId) {
                    let temp = this.studentArr[index];
                    temp.noPeople = true
                    this.studentArr.splice(index, 1, temp)
                  }
                })
                break
              case 201: //操作超时
                this.studentArr.forEach((item, index, arr) => {
                  if (item.id == studentId) {
                    let temp = this.studentArr[index];
                    temp.noClick = true
                    this.studentArr.splice(index, 1, temp)
                  }
                })
                break;
              case 202:  //解除无人检测上报
                this.studentArr.forEach((item, index, arr) => {
                  if (item.id == studentId) {
                    let temp = this.studentArr[index];
                    temp.noPeople = false
                    this.studentArr.splice(index, 1, temp)
                  }
                })
                break
              case 203: //解除操作超时上报
                this.studentArr.forEach((item, index, arr) => {
                  if (item.id == studentId) {
                    let temp = this.studentArr[index];
                    temp.noClick = false
                    this.studentArr.splice(index, 1, temp)
                  }
                })
                break;
              case 204:  //举手上报
                this.studentArr.forEach((item, index, arr) => {
                  if (item.id == studentId) {
                    let temp = this.studentArr[index];
                    temp.handsup = true
                    this.studentArr.splice(index, 1, temp)
                  }
                })
                break;
              case 205: //设备在线状态消息
                this.studentArr.forEach((item, index, arr) => {
                  if (item.id == studentId) {
                    let temp = this.studentArr[index];
                    temp.is_online = messageData.message
                    this.studentArr.splice(index, 1, temp)
                  }
                })
                break
            }
          } else if (type === 'command') {
            switch (messageData.messageType) {
              case 23: //锁屏状态
                this.studentArr.forEach((item, index, arr) => {
                  if (item.id == studentId) {
                    let temp = this.studentArr[index];
                    temp.isLock = 1
                    this.studentArr.splice(index, 1, temp)
                  }
                })
                break
              case 24: //退出锁屏状态
                this.studentArr.forEach((item, index, arr) => {
                  if (item.id == studentId) {
                    let temp = this.studentArr[index];
                    temp.isLock = 0
                    this.studentArr.splice(index, 1, temp)
                  }
                })
                break
            }
          } else if (type === 'data') {
            switch (messageData.messageType) {
              case 100: //屏幕缩略图消息
                this.studentArr.forEach((item, index, arr) => {
                  if (item.id == studentId) {
                    let temp = this.studentArr[index];
                    this.studentArr.splice(index, 1, temp)
                    let docId = "studentScreen" + studentId
                    let imageUrl = this.decompressToImgUrl(messageData.message)
                    const element = document.getElementById(docId)
                    // 设置背景图片
                    if (element) {
                      element.style.backgroundImage = `url(${imageUrl})`;
                    }
                  }
                })
                break;
              case 101: //屏幕截图图消息
                this.studentArr.forEach((item, index, arr) => {
                  if (item.id == studentId) {
                    let temp = this.studentArr[index];
                    let imageUrl = this.decompressToImgUrl(messageData.message)
                    temp.screenImg = imageUrl
                    this.studentArr.splice(index, 1, temp)
                    const element = document.getElementById("screenImg")
                    if (element) {
                      element.style.display = "block"
                      element.src = imageUrl
                    }
                  }
                })
                break;
              case 102:  //远控地址
                let remoteMessage = JSON.parse(messageData.message)
                if (studentId == this.tempStudent.id) {
                  this.initSunlogin({
                    address: remoteMessage.address,
                    cid: remoteMessage.session
                  })
                }
                break;
            }
          }
        } catch (error) {
          console.log("这是error", error)
        }
      });

    },
    //停止订阅mqtt
    disConnect() {
      if (client != null) {
        client.unsubscribe(this.topicSends);
        client = null;
      }
    },
    doPublish(topicType, messageType, message, retain = false, qos = 0) {
      let topic = "/control/" + this.tempStudent.id + "/" + topicType
      let now = new Date()
      let payload = {messageType: messageType, timestamp: now.toJSON(), message: message};
      payload = JSON.stringify(payload)
      client.publish(topic, payload, {qos: 0, retain: retain}, error => {
        if (error) {
          console.log('Publish error', error)
        }
      })
    },
    //发送提醒
    sendTips() {
      this.doPublish("command", 50, this.tips)
      this.tipsVisible = false
      this.tips = ""
    },

    sendLock() {
      this.tempStudent.isLock = 1
      this.doPublish("command", 23, this.lockText, false)
      this.lockVisible = false
    },
    sendCancelLock() {
      this.tempStudent.isLock = 0
      this.doPublish("command", 24, "", false)
      this.lockVisible = false
    },
    remoteScreenshot() {
      this.doPublish("command", 51, "")
      this.$message.success("截屏成功")
    },
    //远程督学
    setTeachingStatus: debounce(function (status) {
      if (status === true) {
        openRemoteVoiceVideo({
          teacherId: this.teacherId,
          studentId: this.tempStudent.id,
          type: 1
        }).then(res => {
          //登录房间 拉流 请求接口都正常才可以
          let userID = "teacher" + this.teacherId
          const result = this.loginRoom(userID, userID)
          if (result === false) {
            this.$message.error("登录房间失败")
            return
          }
          this.doPublish("command", 0, userID)
          this.intervalId = setInterval(this.checkRemainingTime, 60000) //每分钟检查一次剩余音视频时长
        }).catch(err => {
          this.teach = false
        })
      } else {
        //关闭麦克风和摄像头
        this.mike = this.camera = false
        this.doPublish("command", 1, "")
        let streamId = "teacher" + this.teacherId
        zg.stopPublishingStream(streamId)
        zg.stopPlayingStream(this.tempStudent.id.toString())
        this.logoutRoom()
        closeRemoteVoiceVideo({
          teacherId: this.teacherId,
          studentId: this.tempStudent.id,
          type: 1
        }).then(res => {
        })
      }
      clearInterval(this.intervalId)
    }, 1000),
    changeCamera(status) {
      this.doPublish("command", 2, status)
    },
    changeMike(status) {
      let streamId = "teacher" + this.teacherId
      if (status === true) {
        this.pushStream(streamId, 1)
        zg.on("publisherStateUpdate", ({streamID, state}) => {
          if (streamID === streamId && state === "PUBLISHING") {
            setTimeout(() => {
              this.doPublish("command", 4, state)
            }, 100)
          }
        })
      } else {
        this.doPublish("command", 5, "")
        zg.stopPublishingStream(streamId)
        zg.destroyStream(localStream)
      }
    },
    toControlScreen() {
      openRemoteControl({
        teacherId: this.teacherId
      }).then(res => {
        this.doPublish("command", 21, "")
        this.remoteVisible = true
      }).catch(err => {
      })
    },
    closeRemoteControl() {
      if (sunClient != null) {
        this.$refs.wrapper.innerHTML = ''
        sunClient.disconnect()
        sunClient = null
      }
      this.doPublish("command", 22, "")
      this.remoteVisible = false
    },
    endTeachingControl() {
      this.studentArr.forEach((item, index) => {
        let topic = "/control/" + item.id + "/command"
        let now = new Date()
        let payload = {messageType: 20, timestamp: now.toJSON(), message: -1};
        payload = JSON.stringify(payload)
        client.publish(topic, payload, {qos: 0, retain: true}, error => {
          if (error) {
            console.log('Publish error', error)
          }
        })
      })
      //通知对象结束发送屏幕缩略图
      this.studentArr.forEach((item, index) => {
        let topic = "/control/" + item.id + "/command"
        let now = new Date()
        let payload = {messageType: 26, timestamp: now.toJSON(), message: this.courseId};
        payload = JSON.stringify(payload)
        client.publish(topic, payload, {qos: 0, retain: false}, error => {
          if (error) {
            console.log('Publish error', error)
          }
        })
      })
      endTeaching({
        teacherId: this.teacherId,
        courseId: this.courseId,
        type: 1
      }).then(res => {
      })
    },
    exitTeaching() {
      this.$router.push({name: 'myClassroom'})
    },

    openScreenShot() {
      document.querySelectorAll('[id="screenImg"]')[0].src = this.tempStudent.screenImg;
    },
    openAddMoney(student) {
      this.moneyVisible = true
      this.moneyForm.studentId = student.id
    },
    addStudentMoney() {
      if (this.moneyForm.money === "") {
        this.$message.info("请先选择彩虹币数量")
        return
      }
      setStudentMoney({
        studentId: this.moneyForm.studentId,
        type: 1,
        num: this.moneyForm.money
      }).then(res => {
        this.moneyVisible = false
        this.moneyForm = {studentId: 0, money: ''}
        this.$message.success("成功")
      })
    },
    openFeedback(type, student) {
      this.feedbackForm.studentId = student.id
      this.feedbackForm.type = type
      switch (type) {
        case 'handsUp':
          this.feedbackForm.feedbackText = "学生举手"
          break;
        case 'noClick':
          this.feedbackForm.feedbackText = "该学生三分钟未操作平板"
          break;
        case 'noPeople':
          this.feedbackForm.feedbackText = "识别到该学生三分钟未在平板前面"
          break
      }
      this.feedbackVisible = true
    },
    closeFeedback() {
      this.feedbackVisible = false
      this.studentArr.forEach((item, index, arr) => {
        if (item.id == this.feedbackForm.studentId) {
          let temp = this.studentArr[index];
          temp.handsup = false
          switch (this.feedbackForm.type) {
            case 'handsUp':
              temp.handsup = false
              break;
            case 'noClick':
              temp.noClick = false
              break;
            case 'noPeople':
              temp.noPeople = false
              break
          }
          this.studentArr.splice(index, 1, temp)
        }
      })
    },
    reduceStudentMoney() {
      this.studentArr.forEach((item, index, arr) => {
        if (item.id == this.feedbackForm.studentId) {
          let temp = this.studentArr[index];
          temp.handsup = false
          this.studentArr.splice(index, 1, temp)
        }
      })
      setStudentMoney({
        studentId: this.feedbackForm.studentId,
        type: -1,
        num: 5
      }).then(res => {
        this.feedbackVisible = false
        this.money = ""
        this.$message.success("成功")
      })
    },
    initSunlogin({address, cid}) {
      console.log("这是初始化向日葵")
      const _this = this
      const reg = /PHSRC_(HTTP|HTTPS):\/\/([^/]+):(\d+)*\//
      const matches = address.match(reg)
      if (!sunClient) {
        sunClient = new this.SunloginControl.Client({
          host: matches[2],
          embed: true, // SDK 传true
          ssl: matches[1].indexOf('HTTPS') !== -1, // node环境下可以主动忽略证书校验，即使服务器没有配置也可以运行
          cid,
          port: matches[3],
          debug: false,
          // debug: process.env.NODE_ENV === 'development' // 控制台日志输出，生产环境请关闭debug
        })
      }
      this.SunloginControl.Wasm.preload().then(() => {
        sunClient
          .connect() // 客户端连接开始
          .then(() => {
            _this.showLoading = false
            // 断开连接
            sunClient.on('disconnect', () => {
              _this.showLoading = true
              _this.view = null
              delete _this.view

              // 停止截取浏览器的键盘和鼠标事件，等于桌面变成观看模式
              // 放到业务需要的地方
              if (keyboardHandler) {
                keyboardHandler.stop()
                keyboardHandler = null
              }
              if (mouseHandler) {
                mouseHandler.stop()
                mouseHandler = null
              }

            })
            _this.view = new _this.SunloginControl.Wasm(_this.$refs.wrapper)
            const desktop = new _this.SunloginControl.Plugin.Desktop({
              quality: 10,
            })
            sunClient.connectPlugin(desktop)
            // imageinfo 桌面图像信息
            desktop.on('imageinfo', info => {
              console.log(info)
              _this.view.setImageInfo(info)
            })
            desktop.on('screen', count => {
              console.log('屏幕数量：' + count)
            })
            desktop.on('session', sessions => {
              console.log('系统会话：', sessions)
            })
            desktop.on('stream', (stream, info) => {
              this.framesCount = this.framesCount++
              this.totalBytes = this.totalBytes += info.length
              _this.view.decode(stream, info)
              desktop.sendDecodeFinishMessage(
                _this.framesCount,
                _this.totalBytes
              )
            })
            // 传输鼠标（触摸）& 键盘(Win)事件，不传输任何主控端事件，即为观看
            // moveOutRelease 移出图像区域时自动释放鼠标/触摸
            mouseHandler = desktop.transportMouseEvent(_this.$refs.wrapper)
            keyboardHandler = desktop.transportKeyBoardEvent(_this.$refs.wrapper)
            // 在需要的时候通过这两个对象关闭事件监听 mouseHandler.close() keyboardHandler.close()
          })
          .catch(e => {

            sunClient.disconnect()
            console.log(e)
          })
      })
    },
    checkRemainingTime() {
      checkAvRemainTime({
        teacherId: this.teacherId,
      }).then(res => {
        if (res.data.av_time > 0 && res.data.av_time <= 10) {
          this.$notify({
            title: '通知',
            message: '您的剩余音视频可用时长不足,请充值',
            type: 'warning'
          })
        }else if (res.data.av_time <= 0) {
          this.$notify({
            title: '通知',
            message: '剩余音视频可用时长不足, 请自动退出',
            type: "error"
          })
        }
      })
    },
    handleTaskClick(tab, event) {
      this.queryStudentTask(tab.name)
    },
    queryStudentTask(type) {
      queryStudentTaskById({
        studentId: this.tempStudent.id,
        type: type
      }).then(res => {
        this.taskTableData = res.data
      }).catch(err => {
        console.log(err)
      })
    },
    openDetailTask(id) {
      this.taskDetailVisible = true
      getTaskDetail({
        studentId: this.tempStudent.id,
        taskId: id
      }).then(res => {
        this.taskDetailData = res.data
        this.taskInfo = res.otherData
      }).catch(err => {
        console.log(err)
      })
    },
  }
}
</script>

<style scoped>
.top_box {
  background-repeat: no-repeat;
  background-size: 100%;
  width: 320px;
  height: 200px;
  background-color: black;
  margin: 10px;
}
.wrapper {
  height: 100%;
  display: flex;
  justify-content: center;
}

.msg-placeholder {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
}
.msg-placeholder .msg-text {
  color: #fff;
}

.msg-placeholder .loading {
  height: 20px;
  margin-right: 10px;
  display: inline-block;
}

.msg-placeholder .loading span {
  display: inline-block;
  width: 8px;
  height: 100%;
  border-radius: 4px;
  margin: 0 1px;
  background: #ff8a56;
  animation: load 1s ease infinite;
}

.msg-placeholder .loading span:nth-child(2) {
  animation-delay: 0.2s;
}

.msg-placeholder .loading span:nth-child(3) {
  animation-delay: 0.4s;
}

.msg-placeholder .loading span:nth-child(4) {
  animation-delay: 0.6s;
}

.msg-placeholder .loading span:nth-child(5) {
  animation-delay: 0.8s;
}

@keyframes load {
  0%,
  100% {
    height: 10px;
    background: #ff8a56;
  }
  50% {
    height: 20px;
    margin: -5px 1px;
    background: #ff895679;
  }
}
</style>


<style >
.custom-dialog .el-dialog__body {
  height: calc(100% - 50px); /* 假设header是50px高度 */
  max-height: 700px !important;
}
.custom-dialog .el-dialog__headerbtn {
  background-image: url('https://jiaoguanyi008.oss-cn-shenzhen.aliyuncs.com/img/close.png');
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  width: 60px; /* 根据你的图标大小调整 */
  height: 60px; /* 根据你的图标大小调整 */
}

.custom-dialog .el-dialog__headerbtn i {
  display: none;
}

.wrapper,
.msg-placeholder {
  height: 100%;
}

.loading span {
  display: inline-block;
  width: 10px;
  height: 10px;
  margin: 2px;
  background-color: #409eff;
  animation: loading 1s infinite ease-in-out;
}

@keyframes loading {
  0%, 80%, 100% { transform: scale(0); }
  40% { transform: scale(1); }
}
</style>
